/*
 * ROLLOUT for FXGA
 * (c)NEC Home Electronics,Ltd.
 * (c)1996 Bio100%
 */
#include	<system.h>
#include	<v93.h>
#include	<nt.h>
#include	<soundbox.h>
#include	<adp.h>
#include	<farl.h>
#include	<agl.h>
#include	<asl.h>
#include	<common.h>
#include	<libm.h>
#include	<intlib.h>
#include	<pio.h>

// ADPCMファイルヘッダーチェック用
#define ID_RIFF 'FFIR'
#define ID_WAVE 'EVAW'
#define ID_FMT  ' tmf'

#define	FADERATE	64
#define	MAPX		7
#define	MAPZ		400
#define	MAXSPEED	35
#define	MINSPEED	0
#define	BASESPEED	0x04
#define	MAPSTEP		0x40
#define	SHIPY		0
#define	MAXENEMY	40
#define	MAXMSL		5
#define	MAXEMSL		5
#define	MAXJIMEN	8
#define	MAXBAKU		8
#define	MAXCHAR		512
#define	MAXPCM		4
#define	MAXRANK		7
#define	MAXKING		4
#define	FSX			MAPX*MAPSTEP
#define	FSY			0x100
#define	FSZ			0x480

// ADPCM番号
#define	ADP_BBAKU	0
#define	ADP_NSHOT	1
#define	ADP_ZBAKU	2
#define	ADP_DAMAGE	3

// スプライト番号
#define	HED_BIGFONT	256
#define	HED_WHITE	256+64
#define	HED_LIFE	256+65
#define	HED_SPEED	256+67
#define	HED_NEC		256+80
#define	HED_BIO		256+80+1
#define	HED_IWA		256+80+2

// 敵番号
#define	E_PIRAMID	1
#define	E_RING		2
#define	E_ENGINE	3
#define	E_ROCK		4
#define	E_SNOW		5
#define	E_POLE		6
#define	E_MSL		7

ASLSct			sct;
ASLSource		src[MAXCHAR];
unsigned short  buf[163840];
unsigned short  kingfile[MAXKING][130000];
unsigned short	workdat[512];
unsigned char	map[MAPX][MAPZ];
int				charnumber = 0;		// 登録スプライト数
int				xcount, ycount, zcount;
unsigned int 	randomseed;
object			oe[MAXENEMY];		// 敵
object			om[MAXMSL];			// 自弾
object			oem[MAXEMSL];		// 敵弾
object			os;					// 自機
object			oj[MAXJIMEN];		// 地面
object			ob[MAXBAKU];		// 爆発
Material		mt;					// 材質
int				bossflag;
int				gamecount;
int				animecount;
int				startcount;
int				deadcount;
int				mutekicount;
int				skipflag;
int				pauseflag = 0;
int				stage;
unsigned long	pcmblock = 0L;
unsigned char	pcmbuffer[65000];
int				extend[2];

// ポリゴンデータ
int model1[]={
	#include "ship.c"		// 自機
	};
int model2[]={
	#include "tama.c"		// 自弾
	};
int model3[]={
	#include "baku.c"		// 爆発
	};
int model4[]={
	#include "engine.c"		// エンジン
	};
int model5[]={
	#include "ring.c"		// リング
	};
int model6[]={
	#include "piramid.c"	// ピラミッド
	};
int model7[]={
	#include "ground.c"		// 地面
	};
int model8[]={
	#include "etama.c"		// 敵弾
	};
int model9[]={
	#include "boss1.c"		// Boss I
	};
int model10[]={
	#include "boss2.c"		// Boss II
	};
int model11[]={
	#include "mstar.c"		// モーニングスター
	};
int model12[]={
	#include "cube.c"		// 雪
	};
int model13[]={
	#include "pole.c"		// 柱
	};
int model14[]={
	#include "boss3.c"		// Boss III
	};
int model15[]={
	#include "spin.c"		// Boss III Missle
	};

// 物体の構造体
typedef struct	status{
	int	x;
	int	y;
	int	z;
	int	speed;
	int	xspeed;
	int	yspeed;
	int	zspeed;
	int	xdir;
	int	ydir;
	int	zdir;
	int	deg;
	int	xsize;
	int	ysize;
	int	zsize;
	int	flag;
	int	type;
	int	score;
	int	hp;
	};
struct status	ship;				// 自機
struct status	enemy[MAXENEMY];	// 敵
struct status	jimen[MAXJIMEN];	// 地面
struct status	msl[MAXMSL];		// 自弾
struct status	emsl[MAXEMSL];		// 敵弾
struct status	baku[MAXBAKU];		// 爆発

// ランキングデータ
struct	rankdat{
	int	score;
	unsigned char *name;
	}rank[MAXRANK]={
	70000,"TKU   ",
	60000,"NOB   ",
	50000,"FUK   ",
	40000,"ISK   ",
	30000,"FUJ   ",
	20000,"YSK   ",
	10000,"HTJ   "};

// ADPCMファイルヘッダー用構造体
typedef struct adpfileheader_t{
	unsigned long   afFileID;             // RIFF
	unsigned long   afFileSize;
	unsigned long   afFileType;           // WAVE
	unsigned long   afFormatID;           // fmt
	unsigned long   afFormatSize;
	unsigned short  afFormatType;         // フォーマットタイプ
	unsigned short  afNumberOfChannel;    // チャンネル数
	unsigned long   afSamplingRate;       // サンプリングレート
	unsigned long   afTransferByte;       // 転送レート
	unsigned short  afSampleCount;        // サンプル数
	unsigned short  afBitOfNumber;        // 量子化ビット
	unsigned long   afDataID;             // データＩＤ
	unsigned long   afDataSize;           // データサイズ
	}ADPFILEHEAD;

ADPFILEHEAD		aFileHead[MAXPCM];
struct PCMINFO	pInfo[MAXPCM];
struct PCMVOL	pcmvol;

extern unsigned short i5c4yuv_col[];
extern unsigned long __ulSyncCounter;

int main (void);
void title (void);
void gamemain (void);
void shipcontrol (void);
int hitcheck (int num);
void enemyinit (int i,int num);
void enemycontrol (void);
void bossinit (void);
void bosscontrol (int i);
void jimeninit (void);
void jimencontrol (void);
void mslinit (void);
void mslcontrol (void);
int mslhitcheck (int o, int m);
int emslhitcheck (int m);
void enemymslinit (int num);
void enemymslcontrol (void);
void bakuinit (int x, int y, int z, int xs, int ys, int zs);
void bakucontrol (void);
void valinit (void);
void logodsp (void);
void setobject (void);
void setcamera (void);
void putobject (void);
void extendcheck (void);
void ending (void);
void rankdsp (void);
void nameentry (int num);
void entrycheck (void);
void faceinit (void);
void facedsp (void);

void SystemInitialize (void);
void KingInitialize (void);
void SetHiddenClear (void);
void InitSystem (void);
void InitScreen (void);
void MpdLoad (unsigned char *filename);
void HedLoad (int bank, unsigned char *filename);
void KingLoad (int num, unsigned char *filename);
void KingDsp (int num);
int AdpLoad (int num, unsigned char *filename);
void SrcSet (unsigned short bank, int xsize, int ysize, int xnum, int ynum);
void SprPut (int x, int y, int pat);
void SprRotZoomPut (int x, int y, int r, int z, int pat);
void StrDsp (int x, int y, unsigned char *str);
void StrDspBig (int x, int y, unsigned char *str);
void NumDsp (int x, int y, unsigned long val);
void NumDspBig (int x, int y, unsigned long val);
void NumDspBig2 (int x, int y, unsigned long val, int k );
void PaletteChange (int palettenumber, unsigned short yuv);
void PaletteFadeBlack (int mode, int start, int end);
void PaletteFadeWhite (int mode, int start, int end);
void MakePaletteDataBlack (int i, int j);
void MakePaletteDataWhite (int i, int j);
int random (int num);
void WriteTextureBuffer (int bank, int x, int y, int data);
void DspWait (void);
void PcmPlay (int ch, int num);
int ButtonCheck (void);
void Wait (int c);
void LoadDsp(int num,int sum);


/*
 * メイン
 */
int
main()
	{
	SystemInitialize();
	KingInitialize();

	// スプライトデータの読み込みと登録
	charnumber = 0;
	HedLoad(13,"HTJFONT.HED");
	LoadDsp(1,8);
	HedLoad(0,"RUN01.HED");
	LoadDsp(2,8);
	HedLoad(1,"LOGO.HED");
	HedLoad(2,"IWA.HED");
	LoadDsp(3,8);

	// BGデータ読み込み
	KingLoad(0,"TITLE.BIN");
	LoadDsp(4,8);
	KingLoad(1,"SKY2.BIN");
	LoadDsp(5,8);
	KingLoad(2,"KABE.BIN");
	LoadDsp(6,8);
	KingLoad(3,"IWA.BIN");
	LoadDsp(7,8);

	// ADPCMデータ読み込み
	AdpLoad(0,"SBAKU.ADP");
	AdpLoad(1,"NSHOT.ADP");
	AdpLoad(2,"ZBAKU.ADP");
	AdpLoad(3,"DAMAGE.ADP");
	LoadDsp(8,8);

	FX73_cmap_i5c4();
	skipflag = 0;

	logodsp();

	FarlSetPEICMaskReg(FARL_ICMASK_I5C4);
	FarlSetTEControlReg(FARL_TE_LTEN|FARL_TE_ICM| FARL_TE_SPEN| FARL_TE_BCE);

	SetHiddenClear();

	AGLResetLight(AGL_LIGHT0);
	AGLRotateLightX(AGL_LIGHT0, 2820);
	AGLRotateLightY(AGL_LIGHT0, 1100);
	AGLRotateLightZ(AGL_LIGHT0, 0);

	DspWait();
	KINGDispOn();                                 // HuC6272 表示オン
	title();

	return	0;
	}

/*
 * タイトル
 */
void
title()
	{
	int	a;

	KingDsp(0);
	FX73_cmap_i5c4();
	DspWait();

	randomseed = 0;
	while(1)
		{
		a++;
		if ( a > 60 ) a = 0;
		randomseed++;
		if ( randomseed > 50000 ) randomseed = 0;
		get_pad();
		if ( pad00.KD_TRG & KP_run || pad00.KD_TRG & KP_1 ) break;

//		StrDspBig(16,72,"ROLLOUT");
//		StrDsp(16,200,"(C)NEC Home Electronics,Ltd.");
		StrDsp(16,210,"(C)1996 Bio100%");
		if ( a < 40 ) StrDsp(120,140,"PUSH RUN BUTTON");

		DspWait();
		}

	stage = -1;
	ship.hp = 4;
	ship.score = 0;
	extend[0] = extend[1] = 0;

	gamemain();
	}

/*
 * ゲームメイン
 */
void
gamemain()
	{
	int	i,j;
	int	a;

	KingDsp(1);
	valinit();

	// パレットの変更とマップ読み込み
	if ( stage == 0 )
		{
		i5c4yuv_col[257] = 0x4030;
		i5c4yuv_col[258] = 0x2030;
		FX73_cmap_i5c4();
		MpdLoad("RUN.MPD");
		}
	else if ( stage == 1 )
		{
		i5c4yuv_col[257] = 0x40c0;
		i5c4yuv_col[258] = 0x20c0;
		FX73_cmap_i5c4();
		MpdLoad("RUN2.MPD");
		}
	else
		{
		i5c4yuv_col[257] = 0x309f;
		i5c4yuv_col[258] = 0x109f;
		FX73_cmap_i5c4();
		MpdLoad("RUN3.MPD");
		}

	irq_enable();
	get_pad();		// Dummy Read

	// メインループ
	while(1)
		{
		__ulSyncCounter = 0;

		// 一時停止
		if ( pauseflag )
			{
			while(1)
				{
				get_pad();
				if ( pad00.KD_TRG & KP_run )
					{
					pauseflag = 0;
					break;
					}
				}
			}

		animecount++;
		if ( animecount > 35 ) animecount = 0;

		// ship.type は名前には関係なくカウンタとして使っている
		ship.type += (ship.zspeed + BASESPEED);
		if ( ship.type > 116 )
			{
			ship.type -= 116;
			gamecount++;
			if ( gamecount >= MAPZ )
				{
				gamecount = 0;
				if ( bossflag == 0 )
					{
					for ( i = 0 ; i < MAXENEMY ; i++ )
						{
						enemy[i].flag = 0;
						}
					bossinit();
					}
				}
			if ( bossflag == 0 )
				{
				for ( i = 0 ; i < MAPX ; i++ )
					{
					a = map[i][gamecount];
					if ( a > 0 ) enemyinit(i,a);
					}
				}
			if ( gamecount%4 == 1 ) jimeninit();
			}

		shipcontrol();
		enemycontrol();
		mslcontrol();
		enemymslcontrol();
		jimencontrol();
		bakucontrol();

		extendcheck();

		setobject();
		setcamera();
		putobject();

		while(__ulSyncCounter < 3);
		}
	}

/*
 * 自機コントロール
 */
void
shipcontrol()
	{
	int		i,a,b;

	if ( ship.flag == 0 ) return;

	// 爆発中の処理
	if ( ship.flag > 1 )
		{
		ship.flag++;
		if ( ship.flag > 9 )
			{
			os.geometryTop = model1;
			os.geometryLength = sizeof(model1) / sizeof(int);
			os.material = NULL;
			ship.flag = 1;
			mutekicount = 50;
			ship.hp--;
			if ( ship.hp < 0 )
				{
				ship.hp = 0;
				ship.flag = 0;
				deadcount++;
				}
			}
		return;
		}

	// 通常の処理
	get_pad();
	if ( pad00.KD_DAT & KP_up )
		{
		ship.zspeed += 2;
		if ( ship.zspeed > MAXSPEED ) ship.zspeed = MAXSPEED;
		}
	else if ( pad00.KD_DAT & KP_down )
		{
		ship.zspeed -= 2;
		if ( ship.zspeed < MINSPEED ) ship.zspeed = MINSPEED;
		}
	if ( pad00.KD_DAT & KP_right )
		{
		ship.x -= ship.xspeed;
		if ( ship.x < 0 ) ship.x = 0;
		if ( ship.deg < 0 ) ship.deg = 0;
		ship.deg++;
		if ( ship.deg > 15 ) ship.deg = 15;
		}
	else if ( pad00.KD_DAT & KP_left )
		{
		ship.x += ship.xspeed;
		if ( ship.x > FSX ) ship.x = FSX;
		if ( ship.deg > 0 ) ship.deg = 0;
		ship.deg--;
		if ( ship.deg < -15 ) ship.deg = -15;
		}
	else
		{
		if ( ship.deg > 0 ) ship.deg--;
		if ( ship.deg < 0 ) ship.deg++;
		}

	if ( bossflag ) ship.zspeed = MAXSPEED;

	if ( !bossflag && ship.y <= SHIPY )
		{
		ship.score += ship.zspeed*ship.zspeed/200;
		}

	// 一時停止
	if ( pad00.KD_TRG & KP_run ) pauseflag = 1;

	// 自弾発射
	if ( pad00.KD_TRG & KP_1 ) mslinit();

	// ジャンプ
	if ( pad00.KD_TRG & KP_2 && ship.yspeed >= -8 && ship.yspeed <= 0)
		{
		ship.yspeed = 30;
		}
	else
		{
		ship.yspeed -= 3;
		if ( ship.y <= SHIPY )
			{
			ship.yspeed = 0;
			}
		}
	ship.y += ship.yspeed;
	if ( ship.y < SHIPY ) ship.y = SHIPY;
	if ( ship.y > FSY ) ship.y = FSY;

	if ( mutekicount ) return;

	// 敵との当たり判定
	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag )
			{
			if ( hitcheck(i) )
				{
				PcmPlay(1,ADP_BBAKU);
				ship.flag = 2;
				os.geometryTop = model3;
				os.geometryLength = sizeof(model3) / sizeof(int);
				os.material = NULL;
				enemy[i].hp--;
				if ( enemy[i].hp <= 0 )
					{
					enemy[i].flag = 2;
					oe[i].geometryTop = model3;
					oe[i].geometryLength = sizeof(model3) / sizeof(int);
					oe[i].material = NULL;
					}
				}
			}
		}

	// 敵弾との当たり判定
	for ( i = 0 ; i < MAXEMSL ; i++ )
		{
		if ( emsl[i].flag )
			{
			if ( emslhitcheck(i) )
				{
				PcmPlay(1,ADP_BBAKU);
				ship.flag = 2;
				os.geometryTop = model3;
				os.geometryLength = sizeof(model3) / sizeof(int);
				os.material = NULL;
				emsl[i].flag = 0;
				}
			}
		}
	}

/*
 * 自機と敵の当たり判定
 */
int
hitcheck(int num)
	{
	int	a,b,c,p,q,r;

	if ( ship.x > enemy[num].x )
		{
		a = ship.x - enemy[num].x;
		}
	else
		{
		a = enemy[num].x - ship.x;
		}
	if ( ship.y > enemy[num].y )
		{
		b = ship.y - enemy[num].y;
		}
	else
		{
		b = enemy[num].y - ship.y;
		}
	if ( ship.z > enemy[num].z )
		{
		c = ship.z - enemy[num].z;
		}
	else
		{
		c = enemy[num].z - ship.z;
		}

	p = ship.xsize + enemy[num].xsize;
	q = ship.ysize + enemy[num].ysize;
	r = ship.zsize + enemy[num].zsize;

	if ( a < p && b < q && c < r ) return 1;

	return	0;
	}

/*
 * 敵初期化
 */
void
enemyinit(int i,int num)
	{
	int	j;

	for ( j = 0 ; j < MAXENEMY ; j++ )
		{
		if ( enemy[j].flag == 0 )
			{
			enemy[j].flag = 1;
			enemy[j].type = num;
			if ( enemy[j].type == E_ENGINE )
				{
				// エンジン
 				oe[j].geometryTop = model4;
				oe[j].geometryLength = sizeof(model4) / sizeof(int);
				oe[j].material = NULL;
				enemy[j].x = i * MAPSTEP + MAPSTEP/2;
				enemy[j].y = random(5)*MAPSTEP + 0x10;
				enemy[j].z = FSZ - 0x04;
				enemy[j].score = 100;
				enemy[j].xsize = MAPSTEP-0x10;
				enemy[j].ysize = MAPSTEP-0x10;
				enemy[j].zsize = MAPSTEP-0x10;
				enemy[j].hp = 1;
				enemy[j].xspeed = 0;
				enemy[j].yspeed = 0;
				enemy[j].zspeed = -BASESPEED;
				}
			else if ( enemy[j].type == E_RING )
				{
				// リング
 				oe[j].geometryTop = model5;
				oe[j].geometryLength = sizeof(model5) / sizeof(int);
				oe[j].material = NULL;
				enemy[j].x = i * MAPSTEP + MAPSTEP/2;
				enemy[j].y = random(5)*MAPSTEP + 0x10;
				enemy[j].z = 0x40;
				enemy[j].score = 150;
				enemy[j].xsize = MAPSTEP-0x10;
				enemy[j].ysize = MAPSTEP-0x10;
				enemy[j].zsize = MAPSTEP-0x10;
				enemy[j].hp = 1;
				enemy[j].xspeed = 0;
				enemy[j].yspeed = 0;
				enemy[j].zspeed = 50;
				}
			else if ( enemy[j].type == E_PIRAMID )
				{
				// ピラミッド
 				oe[j].geometryTop = model6;
				oe[j].geometryLength = sizeof(model6) / sizeof(int);
				oe[j].material = NULL;
				enemy[j].x = i * MAPSTEP + MAPSTEP/2;
				enemy[j].y = -0x30;
				enemy[j].z = FSZ - 0x04;
				enemy[j].score = 100;
				enemy[j].xsize = MAPSTEP - 0x20;
				enemy[j].ysize = MAPSTEP + 0x40;
				enemy[j].zsize = MAPSTEP - 0x20;
				enemy[j].hp = 100;
				enemy[j].xspeed = 0;
				enemy[j].yspeed = 0;
				enemy[j].zspeed = -BASESPEED;
				}
			else if ( enemy[j].type == E_ROCK )
				{
				// 岩
 				oe[j].geometryTop = model11;
				oe[j].geometryLength = sizeof(model11) / sizeof(int);
				oe[j].material = NULL;
				if ( i < 3 )
					{
					enemy[j].x = 0;
					enemy[j].xspeed = 10;
					}
				else
					{
					enemy[j].x = 6 * MAPSTEP;
					enemy[j].xspeed = -10;
					}
				enemy[j].y = FSY - 0x10;
				enemy[j].z = FSZ - random(100) - 0x80;
				enemy[j].score = 1000;
				enemy[j].xsize = MAPSTEP - 0x10;
				enemy[j].ysize = MAPSTEP - 0x10;
				enemy[j].zsize = MAPSTEP - 0x10;
				enemy[j].hp = 10;
				enemy[j].yspeed = -4;
				enemy[j].zspeed = -BASESPEED;
				}
			else if ( enemy[j].type == E_SNOW )
				{
				// 雪
 				oe[j].geometryTop = model12;
				oe[j].geometryLength = sizeof(model12) / sizeof(int);
				oe[j].material = NULL;
				enemy[j].x = random(FSX);
				enemy[j].xspeed = random(4)-random(4);
				enemy[j].y = FSY - 0x08;
				enemy[j].z = FSZ - random(100) - 0x100;
				enemy[j].score = 250;
				enemy[j].xsize = MAPSTEP - 0x30;
				enemy[j].ysize = MAPSTEP - 0x30;
				enemy[j].zsize = MAPSTEP - 0x30;
				enemy[j].hp = 1;
				enemy[j].yspeed = -random(10) - 5;
				enemy[j].zspeed = -BASESPEED;
				}
			else if ( enemy[j].type == E_POLE )
				{
				// 柱
 				oe[j].geometryTop = model13;
				oe[j].geometryLength = sizeof(model13) / sizeof(int);
				oe[j].material = NULL;
				enemy[j].x = i * MAPSTEP + MAPSTEP/2;
				enemy[j].y = -0xf0;
				enemy[j].z = 0x40;
				enemy[j].score = 200;
				enemy[j].xsize = MAPSTEP - 0x28;
				enemy[j].ysize = MAPSTEP*8;
				enemy[j].zsize = MAPSTEP - 0x28;
				enemy[j].hp = 10;
				enemy[j].xspeed = 0;
				enemy[j].yspeed = 0;
				enemy[j].zspeed = 50;
				}
			else if ( enemy[j].type == E_MSL )
				{
				// BOSS III ミサイル
 				oe[j].geometryTop = model15;
				oe[j].geometryLength = sizeof(model15) / sizeof(int);
				oe[j].material = NULL;
				enemy[j].x = random(FSX);
				enemy[j].y = random(FSY);
				enemy[j].z = FSZ  - 0x100;
				enemy[j].score = 0;
				enemy[j].xsize = MAPSTEP - 0x28;
				enemy[j].ysize = MAPSTEP - 0x28;
				enemy[j].zsize = MAPSTEP - 0x28;
				enemy[j].hp = 2;
				enemy[j].xspeed = (ship.x - enemy[j].x) / 0x20;
				enemy[j].yspeed = (ship.y - enemy[j].y) / 0x20;
				enemy[j].zspeed = (ship.z - enemy[j].z) / 0x20;
				}
			break;
			}
		}
	}

/*
 * 敵コントロール
 */
void
enemycontrol()
	{
	int	i,j;

	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		// 爆発中の処理
		if ( enemy[i].flag > 1 )
			{
			enemy[i].flag++;
			if ( enemy[i].flag > 9 )
				{
				enemy[i].flag = 0;
				if ( enemy[i].type == 99 )
					{
					skipflag = 0;
					PaletteFadeBlack(0,0,511);
					DspWait();
					DspWait();
					Wait(60);
					gamemain();
					}
				}
			}
		// 通常の処理
		else if ( enemy[i].flag == 1 )
			{
			if ( enemy[i].type == 99 )
				{
				bosscontrol(i);
				continue;
				}
			enemy[i].x += enemy[i].xspeed;
			if ( enemy[i].type == E_ROCK )
				{
				enemy[i].yspeed -= 4;
				enemy[i].y += enemy[i].yspeed;
				if ( enemy[i].y <= 0 ) enemy[i].yspeed = 20;
				}
			else if ( enemy[i].type == E_POLE )
				{
				if ( enemy[i].zspeed > 0 )
					{
					if ( enemy[i].z > FSZ - random(0x100) - 0x100 )
						{
						enemy[i].yspeed = 16;
						enemy[i].zspeed = -BASESPEED;
						}
					}
				if ( enemy[i].y > 0x60 ) enemy[i].yspeed = 0;
				enemy[i].y += enemy[i].yspeed;
				}
			else
				{
				enemy[i].y += enemy[i].yspeed;
				}
			enemy[i].z += (enemy[i].zspeed - ship.zspeed);
			if ( enemy[i].x < 0 || enemy[i].x > FSX ) enemy[i].flag = 0;
			if ( enemy[i].y < -0x500 || enemy[i].y > FSY ) enemy[i].flag = 0;
			if ( enemy[i].z < -0x100 || enemy[i].z > FSZ ) enemy[i].flag = 0;
			if ( (enemy[i].type == E_ENGINE || enemy[i].type == E_RING )
				&& random(30) == 0 && enemy[i].z > 0x100 )
				{
				enemymslinit(i);
				}
			// 自弾との当たり判定
			for ( j = 0 ; j < MAXMSL ; j++ )
				{
				if ( msl[j].flag )
					{
					if ( mslhitcheck(i,j) )
						{
						enemy[i].hp--;
						if ( enemy[i].hp <= 0 )
							{
							PcmPlay(1,ADP_ZBAKU);
							enemy[i].flag = 2;
							oe[i].geometryTop = model3;
							oe[i].geometryLength = sizeof(model3) / sizeof(int);
							oe[i].material = NULL;
							ship.score += enemy[i].score;
							}
						else
							{
							PcmPlay(1,ADP_DAMAGE);
							}
						msl[j].flag = 0;
						}
					}
				}
			}
		}
	}

/*
 * ボス初期化
 */
void
bossinit()
	{
	int	i,j;

	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag == 0 )
			{
			enemy[i].flag = 1;
			enemy[i].type = 99;
			if ( stage == 0 )
				{
				oe[i].geometryTop = model9;
				oe[i].geometryLength = sizeof(model9) / sizeof(int);
				oe[i].material = NULL;
				enemy[i].x = 3 * MAPSTEP;
				enemy[i].y = FSY - 0x10;
				enemy[i].z = FSZ/4 + 0x80;
				enemy[i].xspeed = 0;
				enemy[i].yspeed = -0x02;
				enemy[i].zspeed = 0;
				enemy[i].score = 10000;
				enemy[i].xsize = 0x80;
				enemy[i].ysize = 0x80;
				enemy[i].zsize = 0x80;
				enemy[i].hp = 160;
				enemy[i].deg = 0;
				}
			else if ( stage == 1 )
				{
				oe[i].geometryTop = model10;
				oe[i].geometryLength = sizeof(model10) / sizeof(int);
				oe[i].material = NULL;
				enemy[i].x = 3 * MAPSTEP;
				enemy[i].y = FSY - 0x10;
				enemy[i].z = FSZ/3;
				enemy[i].xspeed = 0;
				enemy[i].yspeed = -0x2;
				enemy[i].zspeed = 0;
				enemy[i].score = 10000;
				enemy[i].xsize = 0x80;
				enemy[i].ysize = 0x80;
				enemy[i].zsize = 0x80;
				enemy[i].hp = 180;
				enemy[i].deg = 0;
				}
			else
				{
				oe[i].geometryTop = model14;
				oe[i].geometryLength = sizeof(model14) / sizeof(int);
				oe[i].material = NULL;
				enemy[i].x = 3 * MAPSTEP;
				enemy[i].y = FSY - 0x10;
				enemy[i].z = FSZ/3;
				enemy[i].xspeed = 0;
				enemy[i].yspeed = -0x2;
				enemy[i].zspeed = 0;
				enemy[i].score = 10000;
				enemy[i].xsize = 0x80;
				enemy[i].ysize = 0x80;
				enemy[i].zsize = 0x80;
				enemy[i].hp = 200;
				enemy[i].deg = 0;
				}
			bossflag = 1;
			break;
			}
		}
	}

/*
 * BOSSコントロール
 */
void
bosscontrol(int i)
	{
	int	xs,ys,zs;
	int	j;
	int	dat[8]={
		  0, 8,  0,-8,  0,-8,  0, 8};	// BOSS2用移動データ

	enemy[i].deg++;
	if ( enemy[i].deg > 159 ) enemy[i].deg = 0;

	if ( enemy[i].hp < 100 )
		{
		if ( animecount%4 == 0 )
			{
			xs = random(30) - random(30);
			ys = random(30) - random(30);
			zs = random(30) - random(30);
			bakuinit(enemy[i].x,enemy[i].y,enemy[i].z,xs,ys,zs);
			}
		enemy[i].z += 2;
		enemy[i].hp--;
		if ( enemy[i].hp <= 0 )
			{
			for ( j = 0 ; j < MAXBAKU ; j++ )
				{
				baku[j].flag = 0;
				}
			PcmPlay(1,ADP_BBAKU);
			enemy[i].flag = 2;
			oe[i].geometryTop = model3;
			oe[i].geometryLength = sizeof(model3) / sizeof(int);
			oe[i].material = NULL;
			ship.score += enemy[i].score;
			for ( j = 0 ; j < MAXBAKU ; j++ )
				{
				xs = random(60) - random(60);
				ys = random(60) - random(60);
				zs = random(60) - random(60);
				bakuinit(enemy[i].x,enemy[i].y,enemy[i].z,xs,ys,zs);
				}
			}
		return;
		}

	if ( stage == 0 )
		{
		// ジャンプ
		if ( enemy[i].yspeed == 0 && animecount == 0 )
			{
			enemy[i].yspeed = 20;
			}
		else
			{
			enemy[i].yspeed -= 2;
			if ( enemy[i].y <= 0x40 ) enemy[i].yspeed = 0;
			}
		}
	else if ( stage == 2 )
		{
		// ジャンプ
		if ( enemy[i].yspeed == 0 )
			{
			enemy[i].yspeed = random(30) + 10;
			}
		else
			{
			enemy[i].yspeed -= 4;
			if ( enemy[i].y <= 0x58 ) enemy[i].yspeed = 0;
			}
		}
	else
		{
		enemy[i].yspeed -= 2;
		if ( enemy[i].y <= 0x50 ) enemy[i].yspeed = 0;
		}

	if ( stage != 2 )
		{
		// 前に突っ込む
		if ( enemy[i].deg > 100 && enemy[i].deg < 120 )
			{
			enemy[i].zspeed = -0x12;
			}
		else if ( enemy[i].deg > 120 && enemy[i].deg < 140 )
			{
			enemy[i].zspeed = 0x12;
			}
		else
			{
			if ( random(5) == 0 ) enemymslinit(i);
			enemy[i].zspeed = 0;
			}
		}
	else
		{
		// 下がる
		if ( enemy[i].deg > 60 && enemy[i].deg < 80 )
			{
			enemy[i].zspeed = +0x1c;
			}
		else if ( enemy[i].deg > 80 && enemy[i].deg < 120 )
			{
			if ( enemy[i].deg%4 == 0 ) enemyinit(0,E_MSL);
			}
		else if ( enemy[i].deg > 120 && enemy[i].deg < 140 )
			{
			enemy[i].zspeed = -0x1c;
			}
		else
			{
			if ( random(5) == 0 ) enemymslinit(i);
			enemy[i].zspeed = 0;
			}
		}
	if ( stage != 0 ) enemy[i].xspeed = dat[enemy[i].deg/20];

	enemy[i].x += enemy[i].xspeed;
	enemy[i].y += enemy[i].yspeed;
	enemy[i].z += enemy[i].zspeed;
	if ( enemy[i].x < -0x100 || enemy[i].x > FSX+0x100 ) enemy[i].flag = 0;
	if ( enemy[i].y < -0x500 || enemy[i].y > FSY+0x200 ) enemy[i].flag = 0;
	if ( enemy[i].z < -0x100 || enemy[i].z > FSZ+0x100 ) enemy[i].flag = 0;

	// 自弾との当たり判定
	for ( j = 0 ; j < MAXMSL ; j++ )
		{
		if ( msl[j].flag )
			{
			if ( mslhitcheck(i,j) )
				{
				enemy[i].hp--;
				if ( enemy[i].hp < 0 )
					{
					PcmPlay(1,ADP_ZBAKU);
					enemy[i].flag = 2;
					oe[i].geometryTop = model3;
					oe[i].geometryLength = sizeof(model3) / sizeof(int);
					oe[i].material = NULL;
					ship.score += enemy[i].score;
					}
				else
					{
					PcmPlay(1,ADP_DAMAGE);
					}
				msl[j].flag = 0;
				}
			}
		}
	}

/*
 * 地面初期化
 */
void
jimeninit()
	{
	int	i;

	for ( i = 0 ; i < MAXJIMEN ; i++ )
		{
		if ( jimen[i].flag == 0 )
			{
			jimen[i].flag = 1;
			jimen[i].x = 3 * MAPSTEP + MAPSTEP/2;
			jimen[i].y = -0x40;
			jimen[i].z = FSZ - 0x08;
			jimen[i].xspeed = 0;
			jimen[i].yspeed = 0;
			jimen[i].zspeed = -BASESPEED;
			break;
			}
		}
	}

/*
 * 地面コントロール
 */
void
jimencontrol()
	{
	int	i,j;

	for ( i = 0 ; i < MAXJIMEN ; i++ )
		{
		if ( jimen[i].flag )
			{
			jimen[i].x += jimen[i].xspeed;
			jimen[i].y += jimen[i].yspeed;
			jimen[i].z += (jimen[i].zspeed - ship.zspeed);
			if ( jimen[i].x < 0 || jimen[i].x > FSX ) jimen[i].flag = 0;
			if ( jimen[i].y < -0x500 || jimen[i].y > FSY ) jimen[i].flag = 0;
			if ( jimen[i].z < -0x150 || jimen[i].z > FSZ ) jimen[i].flag = 0;
			}
		}
	}

/*
 * 自弾初期化
 */
void
mslinit()
	{
	int	i,j;

	for ( i = 0 ; i < MAXMSL ; i++ )
		{
		if ( msl[i].flag == 0 )
			{
			msl[i].flag = 1;
			msl[i].x = ship.x;
			msl[i].y = ship.y + 0x10;
			msl[i].z = ship.z;
			msl[i].type = 1;
			msl[i].xspeed = 0;
			msl[i].yspeed = 0;
			msl[i].zspeed = 0x28;
			msl[i].xsize = 0x20;
			msl[i].ysize = 0x20;
			msl[i].zsize = 0x20;
			PcmPlay(0,ADP_NSHOT);
			break;
			}
		}
	}

/*
 * 自弾コントロール
 */
void
mslcontrol()
	{
	int	i,j;

	for ( i = 0 ; i < MAXMSL ; i++ )
		{
		if ( msl[i].flag )
			{
			msl[i].x += msl[i].xspeed;
			msl[i].y += msl[i].yspeed;
			msl[i].z += msl[i].zspeed;
			if ( msl[i].x < 0 || msl[i].x > FSX ) msl[i].flag = 0;
			if ( msl[i].y < -0x100 || msl[i].y > FSY ) msl[i].flag = 0;
			if ( msl[i].z < 0 || msl[i].z > FSZ-0x40 ) msl[i].flag = 0;
			}
		}
	}

/*
 * 自弾と敵との当たり判定
 */
int
mslhitcheck(int o,int m)
	{
	int	a,b,c,p,q,r;

	if ( enemy[o].x > msl[m].x )
		{
		a = enemy[o].x - msl[m].x;
		}
	else
		{
		a = msl[m].x - enemy[o].x;
		}
	if ( enemy[o].y > msl[m].y )
		{
		b = enemy[o].y - msl[m].y;
		}
	else
		{
		b = msl[m].y - enemy[o].y;
		}
	if ( enemy[o].z > msl[m].z )
		{
		c = enemy[o].z - msl[m].z;
		}
	else
		{
		c = msl[m].z - enemy[o].z;
		}

	p = enemy[o].xsize + msl[m].xsize;
	q = enemy[o].ysize + msl[m].ysize;
	r = enemy[o].zsize + msl[m].zsize;

	if ( a < p && b < q && c < r ) return 1;

	return	0;
	}

/*
 * 敵弾と自機との当たり判定
 */
int
emslhitcheck(int m)
	{
	int	a,b,c,p,q,r;

	if ( ship.x > emsl[m].x )
		{
		a = ship.x - emsl[m].x;
		}
	else
		{
		a = emsl[m].x - ship.x;
		}
	if ( ship.y > emsl[m].y )
		{
		b = ship.y - emsl[m].y;
		}
	else
		{
		b = emsl[m].y - ship.y;
		}
	if ( ship.z > emsl[m].z )
		{
		c = ship.z - emsl[m].z;
		}
	else
		{
		c = emsl[m].z - ship.z;
		}

	p = ship.xsize + emsl[m].xsize;
	q = ship.ysize + emsl[m].ysize;
	r = ship.zsize + emsl[m].zsize;

	if ( a < p && b < q && c < r ) return 1;

	return	0;
	}

/*
 * 敵弾初期化
 */
void
enemymslinit(int num)
	{
	int	i,j;

	for ( i = 0 ; i < MAXEMSL ; i++ )
		{
		if ( emsl[i].flag == 0 )
			{
			emsl[i].flag = 1;
			emsl[i].x = enemy[num].x;
			emsl[i].y = enemy[num].y;
			emsl[i].z = enemy[num].z - 0x08;
			emsl[i].xspeed = (ship.x - enemy[num].x) / 0x10;
			emsl[i].yspeed = (ship.y - enemy[num].y) / 0x10;
			emsl[i].zspeed = (ship.z - enemy[num].z) / 0x10;
			emsl[i].xsize = 0x10;
			emsl[i].ysize = 0x10;
			emsl[i].zsize = 0x10;
			break;
			}
		}
	}

/*
 * 敵弾コントロール
 */
void
enemymslcontrol()
	{
	int	i,j;

	for ( i = 0 ; i < MAXEMSL ; i++ )
		{
		if ( emsl[i].flag )
			{
			emsl[i].x += emsl[i].xspeed;
			emsl[i].y += emsl[i].yspeed;
			emsl[i].z += emsl[i].zspeed;
			if ( emsl[i].x < 0 || emsl[i].x > FSX ) emsl[i].flag = 0;
			if ( emsl[i].y < 0 || emsl[i].y > FSY ) emsl[i].flag = 0;
			if ( emsl[i].z < -0x100 || emsl[i].z > FSZ/2 ) emsl[i].flag = 0;
			}
		}
	}

/*
 * 爆発初期化
 */
void
bakuinit(int x, int y, int z, int xs, int ys, int zs)
	{
	int	i;

	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		if ( baku[i].flag == 0 )
			{
			PcmPlay(0,ADP_ZBAKU);
			baku[i].flag = 1;
			baku[i].x = x;
			baku[i].y = y;
			baku[i].z = z;
			baku[i].xspeed = xs;
			baku[i].yspeed = ys;
			baku[i].zspeed = zs;
			break;
			}
		}
	}

/*
 * 爆発コントロール
 */
void
bakucontrol()
	{
	int	i,j;

	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		if ( baku[i].flag )
			{
			baku[i].flag++;
			if ( baku[i].flag > 16 ) baku[i].flag = 0;
			baku[i].x += baku[i].xspeed;
			baku[i].y += baku[i].yspeed;
			baku[i].z += baku[i].zspeed;
			if ( baku[i].x < 0 || baku[i].x > FSX ) baku[i].flag = 0;
			if ( baku[i].y < -180 || baku[i].y > FSY ) baku[i].flag = 0;
			if ( baku[i].z < 0 || baku[i].z > FSZ ) baku[i].flag = 0;
			}
		}
	}


/*
 * 変数初期化
 */
void
valinit()
	{
	int		i,j;

	os.geometryTop = model1;
	os.geometryLength = sizeof(model1) / sizeof(int);
	os.material = NULL;
	ship.deg = 0;
	ship.speed = 0;
	ship.xspeed = 12;
	ship.yspeed = 0;
	ship.zspeed = MINSPEED + 25;
	ship.x = FSX/2;
	ship.y = SHIPY;
	ship.z = 0;
	ship.xsize = 0x10;
	ship.ysize = 0x10;
	ship.zsize = 0x10;
	ship.flag = 1;
	ship.type = 300;

	for ( i = 0 ; i < MAXJIMEN ; i++ )
		{
		jimen[i].flag = 0;
		oj[i].geometryTop = model7;
		oj[i].geometryLength = sizeof(model7) / sizeof(int);
		oj[i].material = NULL;
		}
	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		enemy[i].flag = 0;
		}
	for ( i = 0 ; i < MAXMSL ; i++ )
		{
		msl[i].flag = 0;
		om[i].geometryTop = model2;
		om[i].geometryLength = sizeof(model2) / sizeof(int);
		om[i].material = NULL;
		}
	for ( i = 0 ; i < MAXEMSL ; i++ )
		{
		emsl[i].flag = 0;
		oem[i].geometryTop = model8;
		oem[i].geometryLength = sizeof(model8) / sizeof(int);
		oem[i].material = NULL;
		}
	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		baku[i].flag = 0;
		ob[i].geometryTop = model3;
		ob[i].geometryLength = sizeof(model3) / sizeof(int);
		ob[i].material = NULL;
		}
	gamecount = animecount = 0;
	bossflag = 0;
	startcount = 50;
	mutekicount = 50;
	deadcount = 0;
	stage++;
	if ( stage > 2 ) ending();
	}

/*
 * ロゴ表示
 */
void
logodsp()
	{
	int	i,j,k,l;

/*	PaletteFadeBlack(0,0,511);
	Wait(60);
	if ( skipflag ) return;
	// NECロゴ
	for ( i = 0 ; i < 16 ; i++ )
		{
		for ( j = 0 ; j < 16 ; j++ )
			{
			SprPut(i*16+8,j*16+8,HED_WHITE);
			}
		}
	SprPut(128,120,HED_NEC);
	DspWait();
	PaletteFadeBlack(1,0,511);
	Wait(120);
	if ( skipflag ) return;
*/	PaletteFadeWhite(0,0,511);
	Wait(60);
	if ( skipflag ) return;

	// Bio100%ロゴ
	for ( i = 0 ; i < FADERATE+1 ; i++ )
		{
		for ( j = 0 ; j < 512 ; j++ )
			{
			MakePaletteDataWhite(i,j);
			}
		if ( ButtonCheck() ) return;
		VSyncWait();
		write_pallet_datas(0, workdat, 512);
		for ( k = 0 ; k < 16 ; k++ )
			{
			for ( l = 0 ; l < 16 ; l++ )
				{
				SprPut(k*16+8,l*16+8,HED_WHITE);
				}
			}
		SprRotZoomPut(128,120,(FADERATE-i)*32,256+(FADERATE-i)*32,HED_BIO);
		DspWait();
		}
	if ( skipflag ) return;
	Wait(120);
	if ( skipflag ) return;
	PaletteFadeBlack(0,0,511);
	Wait(60);
	}

/*
 * 各オブジェクトの設置
 */
void
setobject()
	{
	int	i;
	int	dat[36]={
		  0,  1,  2,  3,  4,  5,  6,  7,  8,
		  8,  7,  6,  5,  4,  3,  2,  1,  0,
		  0,359,358,357,356,355,354,353,352,
		352,353,354,355,356,357,358,359,  0};	// BOSS用揺れデータ

	if ( ship.flag == 1 )
		{
		AGLResetObj(&os);
		AGLRotateObjY(&os,1800);
		AGLScaleObj(&os,0x50,0x50,0x50);
		AGLRotateObjZ(&os,(3600+ship.deg*32)%3600);
		AGLTranslateObj(&os,ship.x,ship.y,ship.z);
		}
	else if ( ship.flag > 1 )
		{
		AGLResetObj(&os);
		AGLScaleObj(&os,0x50,0x50,0x50);
		AGLRotateObjY(&os,ship.flag*400);
		AGLRotateObjZ(&os,ship.flag*400);
		AGLTranslateObj(&os,ship.x,ship.y,ship.z);
		}
	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag == 1 )
			{
			if ( enemy[i].type == E_ENGINE )
				{
				AGLResetObj(&oe[i]);
				AGLScaleObj(&oe[i],0xa0,0xa0,0xa0);
				}
			else if ( enemy[i].type == E_RING )
				{
				AGLResetObj(&oe[i]);
				AGLScaleObj(&oe[i],0xa0,0xa0,0xa0);
				AGLRotateObjZ(&oe[i],(animecount*100)%3600);
				}
			else if ( enemy[i].type == E_PIRAMID )
				{
				AGLResetObj(&oe[i]);
				AGLScaleObj(&oe[i],0x150,0x150,0x150);
				}
			else if ( enemy[i].type == E_ROCK )
				{
				AGLResetObj(&oe[i]);
				AGLScaleObj(&oe[i],0x120,0x120,0x120);
				AGLRotateObjX(&oe[i],(animecount*100)%3600);
				if ( enemy[i].xspeed < 0 )
					{
					AGLRotateObjZ(&oe[i],(animecount*200)%3600);
					}
				else
					{
					AGLRotateObjZ(&oe[i],((35-animecount)*200)%3600);
					}
				}
			else if ( enemy[i].type == E_SNOW )
				{
				AGLResetObj(&oe[i]);
				AGLScaleObj(&oe[i],0x40,0x40,0x10);
				AGLRotateObjX(&oe[i],(animecount*100)%3600);
				AGLRotateObjY(&oe[i],(animecount*200)%3600);
				AGLRotateObjZ(&oe[i],(animecount*400)%3600);
				}
			else if ( enemy[i].type == E_POLE )
				{
				AGLResetObj(&oe[i]);
				AGLScaleObj(&oe[i],0xa0,0xa0,0x400);
				AGLRotateObjX(&oe[i],900);
				}
			else if ( enemy[i].type == E_MSL )
				{
				AGLResetObj(&oe[i]);
				AGLScaleObj(&oe[i],0xa0,0xa0,0xa0);
//				AGLRotateObjX(&oe[i],1800);
				AGLRotateObjZ(&oe[i],(animecount*400)%3600);
				}
			else
				{
				if ( stage == 0 )
					{
					AGLResetObj(&oe[i]);
					AGLScaleObj(&oe[i],0x280,0x280,0x280);
					AGLRotateObjY(&oe[i],1800);
					AGLRotateObjZ(&oe[i],dat[animecount]*10);
					}
				else if ( stage == 1 )
					{
					AGLResetObj(&oe[i]);
					AGLScaleObj(&oe[i],0x280,0x280,0x280);
					AGLRotateObjX(&oe[i],900);
					AGLRotateObjY(&oe[i],animecount*100);
					AGLRotateObjZ(&oe[i],dat[animecount]*10);
					}
				else
					{
					AGLResetObj(&oe[i]);
					AGLScaleObj(&oe[i],0x300,0x300,0x300);
					AGLRotateObjX(&oe[i],2700);
					AGLRotateObjZ(&oe[i],dat[animecount]*10);
					}
				}
			AGLTranslateObj(&oe[i],enemy[i].x,enemy[i].y,enemy[i].z);
			}
		else if ( enemy[i].flag > 1 )
			{
			AGLResetObj(&oe[i]);
			AGLScaleObj(&oe[i],0x100,0x100,0x100);
			AGLRotateObjY(&oe[i],enemy[i].flag*200);
			AGLRotateObjZ(&oe[i],enemy[i].flag*200);
			AGLTranslateObj(&oe[i],enemy[i].x,enemy[i].y,enemy[i].z);
			}
		}
	for ( i = 0 ; i < MAXJIMEN ; i++ )
		{
		if ( jimen[i].flag )
			{
			AGLResetObj(&oj[i]);
			AGLScaleObj(&oj[i],0x380,0x80,0x280);
			AGLTranslateObj(&oj[i],jimen[i].x,jimen[i].y,jimen[i].z);
			}
		}
	for ( i = 0 ; i < MAXMSL ; i++ )
		{
		if ( msl[i].flag )
			{
			AGLResetObj(&om[i]);
			AGLScaleObj(&om[i],0x40,0x40,0x40);
			AGLRotateObjX(&om[i],(animecount*225)%3600);
			AGLRotateObjZ(&om[i],(animecount*225)%3600);
			AGLTranslateObj(&om[i],msl[i].x,msl[i].y,msl[i].z);
			}
		}
	for ( i = 0 ; i < MAXEMSL ; i++ )
		{
		if ( emsl[i].flag )
			{
			AGLResetObj(&oem[i]);
			AGLScaleObj(&oem[i],0x40,0x40,0x40);
			AGLRotateObjX(&oem[i],(animecount*225)%3600);
			AGLRotateObjZ(&oem[i],(animecount*225)%3600);
			AGLTranslateObj(&oem[i],emsl[i].x,emsl[i].y,emsl[i].z);
			}
		}
	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		if ( baku[i].flag )
			{
			AGLResetObj(&ob[i]);
			AGLScaleObj(&ob[i],0x120,0x120,0x120);
			AGLRotateObjY(&ob[i],(baku[i].flag*400)%3600);
			AGLRotateObjZ(&ob[i],(baku[i].flag*400)%3600);
			AGLTranslateObj(&ob[i],baku[i].x,baku[i].y,baku[i].z);
			}
		}
	}

/*
 * カメラ位置の設定
 */
void
setcamera()
	{
	int	camerax;

	AGLResetCamera();
	camerax = FSX/16 + ship.x*7/8;
	AGLTranslateCamera(camerax, ship.y + 0x50, ship.z - 0x20);
	AGLLookAtCamera(camerax, ship.y, FSZ, 0x0, 0x7fff, 0x0);
	AGLRotateCameraZ((3600+ship.deg*2)%3600);
	AGLPerspectiveCamera(0xff80);
	}

/*
 * 各オブジェクトの描画
 */
void
putobject()
	{
	int	i;
	int	speedlevel;
	int	dat[13][2]={ 1,63,  1,54,  2,46,  5,39,  8,32, 13,25, 19,19,
		25,13, 32, 8, 39, 5, 46, 2, 54, 1, 63, 1 };

	if ( ship.flag != 0 && (mutekicount == 0 || animecount%2 == 0) )
		{
		AGLFixPutObj(&os);
		}
	for ( i = 0 ; i < MAXJIMEN ; i++ )
		{
		if ( jimen[i].flag ) AGLFixPutObj(&oj[i]);
		}
	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag ) AGLFixPutObj(&oe[i]);
		}
	for ( i = 0 ; i < MAXMSL ; i++ )
		{
		if ( msl[i].flag ) AGLFixPutObj(&om[i]);
		}
	for ( i = 0 ; i < MAXEMSL ; i++ )
		{
		if ( emsl[i].flag ) AGLFixPutObj(&oem[i]);
		}
	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		if ( baku[i].flag ) AGLFixPutObj(&ob[i]);
		}

	StrDsp(16,16,"SCORE");
	NumDsp(64,16,ship.score);

	speedlevel = 13 * (ship.zspeed+BASESPEED) / MAXSPEED;
	if ( speedlevel > 13 ) speedlevel = 13;
	for ( i = 0 ; i < speedlevel ; i++ )
		{
		SprPut(dat[i][0]+184,dat[i][1]+160,HED_SPEED+i);
		}

	if ( ship.flag != 0 )
		{
		for ( i = 0 ; i < ship.hp ; i++ )
			{
			SprPut(16+i*16,224,HED_LIFE);
			}
		}
	mutekicount--;
	if ( mutekicount < 0 ) mutekicount = 0;
	startcount--;
	if ( startcount < 0 ) startcount = 0;
	if ( startcount > 0 ) StrDspBig(80,110,"READY?");
	if ( deadcount > 0 )
		{
		deadcount++;
		if ( deadcount > 80 )
			{
			skipflag = 0;
			PaletteFadeBlack(0,0,511);
			DspWait();
			DspWait();
			Wait(60);
			entrycheck();
			}
		}
	if ( deadcount > 0 ) StrDspBig(64,110,"GAME OVER");
	DspWait();
	}

/*
 * エクステンドチェック
 */
void
extendcheck()
	{
	// 1回目のエクステンド
	if ( ship.score > 15000 && extend[0] == 0 )
		{
		ship.hp++;
		extend[0] = 1;
		}
	// 2回目のエクステンド
	if ( ship.score > 40000 && extend[1] == 0 )
		{
		ship.hp++;
		extend[1] = 1;
		}
	}

/*
 * エンディング
 */
void
ending()
	{
	int	i,j,a;
	int	ycount;
	unsigned char	*staffdat[200]={
		" "," "," "," "," "," "," "," "," "," ",
		" "," "," "," "," "," "," "," "," "," ",
		"  ROLLOUT          ",
		" "," "," "," "," "," ",
		"Game Design        ",
		"     MASAO MASUTANI",
		" "," "," "," ",
		"Program            ",
		"     MASAO MASUTANI",
		" "," "," "," ",
		"Graphics           ",
		"     MASAO MASUTANI",
		" "," "," "," ",
		"Ending Illustration",
		"     Hiroko Iwasaki",
		" "," "," "," ",
		"Sound              ",
		"     MASAO MASUTANI",
		" "," "," "," ",
		"Special Thanks     ",
		"     ASCIInet bio.*",
		" NIFTY-Serve FGALGL",
		"  Project Team DoGA",
		"     NECﾎｰﾑｴﾚｸﾄﾛﾆｸｽ",
		" "," "," "," "," "," "," "," "," "," ",
		" "," "," "," "," "," "," "," "," "," ",
		"Presented by",
		"      Bio100%      ",
		" "," "," "," "," "," "," "," "," "," ",
		" "," "," "," "," "," "," "," "," "," ",
		" "," "," "," "," "," "," "," "," "," "
		};

	KingDsp(3);
	FX73_cmap_i5c4();

	faceinit();

	get_pad();
	animecount = 0;
	a = ycount = 0;
	while(1)
		{
		animecount++;
		if ( animecount > 35 ) animecount = 0;

		// IWA
		facedsp();

		for ( i = 0 ; i < 25 ; i++ )
			{
			StrDsp(16,i*20-a,staffdat[ycount+i]);
			}
		a++;
		if ( a > 19 )
			{
			a = 0;
			ycount++;
			if ( ycount > 76 ) break;
			}
		DspWait();
		}
	while(1)
		{
		animecount++;
		if ( animecount > 35 ) animecount = 0;

		get_pad();
		if ( pad00.KD_TRG && KP_1 ) break;
		if ( pad00.KD_TRG && KP_run ) break;

		facedsp();
		for ( i = 0 ; i < 25 ; i++ )
			{
			StrDsp(16,i*20-a,staffdat[77+i]);
			}
		DspWait();
		}
	entrycheck();
	}

/*
 * ランキング表示
 */
void
rankdsp()
	{
	int	i,a;
	int	ox,oy;

	KingDsp(2);
	FX73_cmap_i5c4();
	ox = 16;
	oy = 56;
	a = 0;
	while(1)
		{
		if ( a > 120 ) break;

		StrDspBig(80,24,"RANKING");
		for ( i = 0 ; i < MAXRANK ; i++ )
			{
			StrDsp(ox+8,oy+i*24+4,"rank");
			NumDspBig(ox+36+8,oy+i*24,i+1);
			NumDspBig2(ox+64,oy+i*24,rank[i].score,6);
			StrDspBig(ox+168,oy+i*24,rank[i].name);
			}
		a++;
		DspWait();
		VSyncWait();
		}
	PaletteFadeBlack(0,0,511);
	title();
	}

/*
 * ネームエントリー
 */
void
nameentry(int num)
	{
	int	i;
	int	ox,oy;
	int	a,moji;
	int	keycount;

	DspWait();
	KingDsp(2);
	FX73_cmap_i5c4();
	ox = 16;
	oy = 56;
	a = 0;
	moji = 0x41;
	rank[num].name[0] = moji;
	rank[num].name[1] = 0x00;
	rank[num].name[2] = 0x00;
	rank[num].name[3] = 0x00;
	rank[num].name[4] = 0x00;
	keycount = 0;

	// メインループ
	while(1)
		{
		get_pad();
		if ( pad00.KD_DAT & KP_left )
			{
			keycount++;
			}
		else if ( pad00.KD_DAT & KP_right )
			{
			keycount--;
			}
		else
			{
			keycount = 0;
			}
		if ( ((pad00.KD_TRG & KP_right) || keycount < -3) && a < 3 )
			{
			moji++;
			if ( moji > 0x5f ) moji = 0x20;
			keycount = 0;
			}
		else if ( ((pad00.KD_TRG & KP_left) || keycount > 3) && a < 3 )
			{
			moji--;
			if ( moji < 0x20 ) moji = 0x5f;
			keycount = 0;
			}
		rank[num].name[a] = moji;

		if ( pad00.KD_TRG & KP_1 )
			{
			if ( moji == 0x40 )
				{
				rank[num].name[a] = 0x00;
				break;
				}
			else
				{
				a++;
				if ( a > 2 )
					{
					a = 3;
					moji = 0x40;
					}
				}
			}
		else if ( pad00.KD_TRG & KP_2 )
			{
			a--;
			if ( a < 0 ) a = 0;
			moji = rank[num].name[a];
			rank[num].name[a+1] = 0x00;
			}

		StrDspBig(80,24,"RANKING");

		StrDsp(ox+8,oy+num*24+4,"rank");
		NumDspBig(ox+36+8,oy+num*24,num+1);
		NumDspBig2(ox+64,oy+num*24,rank[num].score,6);
		StrDspBig(ox+168,oy+num*24,rank[num].name);

		DspWait();
		VSyncWait();
		}
	}

/*
 * ネームエントリーチェック
 */
void
entrycheck()
	{
	int	i,j;

	for ( i = 0 ; i < MAXRANK ; i++ )
		{
		if ( rank[i].score < ship.score )
			{
			for ( j = MAXRANK - 1 ; j > i ; j-- )
				{
				rank[j].score = rank[j-1].score;
				rank[j].name[0] = rank[j-1].name[0];
				rank[j].name[1] = rank[j-1].name[1];
				rank[j].name[2] = rank[j-1].name[2];
				rank[j].name[3] = rank[j-1].name[3];
				}
			rank[i].score = ship.score;
			nameentry(i);
			break;
			}
		}
	rankdsp();
	}

/*
 * Face Initialize
 */
void
faceinit()
	{
	ship.x = 128;
	ship.y = 128;
	ship.z = 256;
	ship.type = HED_IWA;
	ship.xspeed = random(3);
	ship.yspeed = random(3);
	ship.zspeed = random(5);
	ship.flag = 10;
	}

/*
 * Face Control
 */
void
facedsp()
	{
	ship.flag--;
	if ( ship.flag <= 0 )
		{
		ship.xspeed = random(3) - random(3);
		ship.yspeed = random(3) - random(3);
		ship.zspeed = random(5) - random(5);
		ship.flag = random(100)+50;
		}
	ship.x += ship.xspeed;
	if ( ship.x < 0 )
		{
		ship.x = 0;
		ship.xspeed = -ship.xspeed;
		}
	else if ( ship.x > 255 )
		{
		ship.x = 255;
		ship.xspeed = -ship.xspeed;
		}
	ship.y += ship.yspeed;
	if ( ship.y < 8 )
		{
		ship.y = 8;
		ship.yspeed = -ship.yspeed;
		}
	else if ( ship.y > 234 )
		{
		ship.y = 235;
		ship.yspeed = -ship.yspeed;
		}
	ship.z += ship.zspeed;
	if ( ship.z < 128 )
		{
		ship.z = 128;
		ship.zspeed = -ship.zspeed;
		}
	else if ( ship.z > 511 )
		{
		ship.z = 512;
		ship.zspeed = -ship.zspeed;
		}
	SprRotZoomPut(ship.x, ship.y, animecount*100, ship.z, ship.type);
	}


// ☆基本ライブラリ ===========================================================


// 初期化関係 -----------------------------------------------------------------

/*
 * マシン初期化
 */
void
SystemInitialize()
	{
	// 初期化
	cache_enable();
	DevInit();			// 各種デバイス初期化
	InitSystem();
	InitScreen();
	FX73init();
	FX73_cmap_i5c4();
	FarlInit();
	AGLInit();
	// もう一度初期化しないとADPCMか色がおかしくなる?
	DevInit();
	InitSystem();

	AdpcmVolume(CHANNEL_1, MIN_PCM_VOLUME, MIN_PCM_VOLUME);
	AdpcmVolume(CHANNEL_2, MIN_PCM_VOLUME, MIN_PCM_VOLUME);
	AdpcmInit();
	AdpcmVolume(CHANNEL_1, MAX_PCM_VOLUME, MAX_PCM_VOLUME);
	AdpcmVolume(CHANNEL_2, MAX_PCM_VOLUME, MAX_PCM_VOLUME);

	pcmvol.pvoll = 0x28;
	pcmvol.pvolr = 0x28;
	set_pcm_vol(&pcmvol);

	ASLSetSpriteWindow( 0, 0, 255, 239 );
	VSyncInt();
	}

/*
 * KING面初期化
 */
void
KingInitialize()
	{
	KINGScreen(0);								// 画面モード16m色
	KINGDispOff();								// HuC6272 表示オフ
	KINGCylinder(KING_BG0,1);					// 茶筒モード
	KINGChangeSize0(DISP_NORMAL);				// 画面幅設定
	dispoff(bg | spr | rain | bg1 | bg2 | bg3);	// 他画面オフ
	dispon(bg | spr | bg0);						// 画面ON
	KINGCls(KING_BG0);							// 画面消去
	KINGDispOff();								// HuC6272 表示オン
	}

/*
 * Hidden Clear設定
 */
void
SetHiddenClear()
	{
	FarlSetMemReg(FARL_DISPLAY_CONTROL_REG,
			FARL_DISPLAY_CONTROL_BCM0 | FARL_DISPLAY_CONTROL_HCE);
	FarlSetPEMaskReg(0x3fff);
	FarlSetPEClearMaskReg(0x3fff);
	FarlSetPEClearColorReg(0x000);
	FarlValidateSwap();
	}

/*
 * システム初期化
 */
void
InitSystem()
	{
	irq_disable();
	cache_clear();
	cache_enable();
    set_irq_mask(
		BIT_IRQM_SIO | 
		BIT_IRQM_7A | 
		BIT_IRQM_7B |
		BIT_IRQM_KING |
		BIT_IRQM_KP |
		BIT_IRQM_EXT |
		BIT_IRQM_TMI |
		BIT_IRQM_AERR |
		0
		);

	set_irq_prio(IRQ_PRIOA, IRQ_KP);
	set_irq_vector(&int_pad, IRQ_LEVELA);

    reset_irq_mask(
//			BIT_IRQM_SIO | 
//			BIT_IRQM_7A | 
//			BIT_IRQM_7B |
//			BIT_IRQM_KING |
			BIT_IRQM_KP |
//			BIT_IRQM_EXT |
//			BIT_IRQM_TMI |
//			BIT_IRQM_AERR |
			0
		);

	set_irq_level(0x0007);
	IrqOn(XINT_72);				// HuC6272 割り込みを有効に
	irq_enable();
	init_get_pad();
	get_pad();
	}

/*
 * 画面初期化
 */
void
InitScreen()
	{
	int i;

	init_nt();	// init Hu6261 device
	init_70();
	dispon(bg | spr | bg0 | bg1 | bg2 | bg3 | rain );
	dispoff( /*bg | spr |*/ bg0 | bg1 | bg2 | bg3 | rain );
	set_nt_mode(interlace | inter_sync | mode_5M | mode_sp256 | mode_bg256);

	cel_off(bg);
	cel_off(spr);
	cel_off(bg0);
	cel_off(bg1);
	cel_off(bg2);
	cel_off(bg3);
	cel_off(rain);
	}


// ファイル関係 ---------------------------------------------------------------

/*
 * MPDファイルの読み込み
 */
void
MpdLoad(unsigned char *filename)
	{
	int	fp, c,i,j;
	int	p,q,r,s;

	pio_putstr( "マップデータを読み込んでいます..." );
	// 読み込み
	fp = pio_fopen(filename, "rb" );
	if ( fp == -1 )
		{
		pio_putstr( "\nファイルが開けませんでした。\n" );
		return;
		}
	pio_fread(fp,32,(char *)buf);
	for ( i = 0 ; i < MAPX ; i++ )
		{
		pio_fread(fp,MAPZ,(unsigned char *)map[i]);
		}
	pio_putstr( "成功。\n" );
	pio_fclose(fp);
	return;
	}

/*
 * HEDファイルの読み込み
 */
void
HedLoad(int bank,unsigned char *filename)
	{
	int	fp, c,i,j;
	int	p,q,r,s;

	pio_putstr( "キャラクタファイルを読み込んでいます..." );
	// 読み込み
	fp = pio_fopen(filename, "rb" );
	if ( fp == -1 )
		{
		pio_putstr( "\nファイルが開けませんでした。\n" );
		return;
		}
	c = (256*256+4) * 2;
	pio_fread(fp,c,(char *)buf);
	c = 0;
	p = buf[c];
	c++;
	q = buf[c];
	c++;
	r = buf[c];
	c++;
	s = buf[c];
	c++;
	for ( i = 0 ; i < q*s ; i++ )
		{
		for ( j = 0 ; j < p*r ; j++ )
			{
			WriteTextureBuffer(bank,j,i,buf[c]);
			c++;
			}
		}
	SrcSet(bank,p,q,r,s);
	pio_putstr( "成功。\n" );
	pio_fclose(fp);
	return;
	}

/*
 * KINGに描画
 */
void
KingLoad(int num, unsigned char *filename)
	{
	int	fp;

	// ファイル読込
	pio_putstr( "背景データを読み込んでいます..." );
	if ( (fp = pio_fopen(filename, "rb")) == -1 )
		{
		pio_putstr("ファイルが開けませんでした。\n");
		return;
		}
	pio_fread(fp,122880,kingfile[num]);
	pio_fclose(fp);
	pio_putstr( "成功。\n" );
	}

/*
 * KingDsp
 */
void
KingDsp(int num)
	{
	KINGDispOff();
	KINGScreen(0);
	KINGCls(KING_BG0);
	KINGTrans(KING_BG0,kingfile[num],2);
	KINGDispOn();
	}


/*
 * ADPCMファイルの読込
 */
int
AdpLoad(int num, unsigned char *filename)
	{
	int	fp;

	pio_putstr( "ADPCMデータを読み込んでいます..." );
	// ファイルオープン
	if ( (fp = pio_fopen(filename, "rb")) == -1 )
		{
		pio_putstr("ファイルが開けませんでした。\n");
		return	0;
		}
	// ヘッダーの読み込み
	if ( pio_fread(fp,sizeof(ADPFILEHEAD),&aFileHead[num])
		!= sizeof(ADPFILEHEAD) )
		{
		pio_putstr("ファイルフォーマットが異常です。\n");
		pio_fclose(fp);
		return	0;
		}
	if ( aFileHead[num].afFileID != ID_RIFF || aFileHead[num].afFileType
		!= ID_WAVE || aFileHead[num].afFormatID != ID_FMT  )
		{
		pio_putstr("ヘッダーが異常です。\n");
		pio_fclose(fp);
		return 0;
		}

	pio_fseek(fp,0,0);
	// ヘッダーに書いてあるサイズ + ヘッダー分読み込む
	if ( pio_fread(fp, aFileHead[num].afDataSize + sizeof(ADPFILEHEAD)
		,pcmbuffer) != aFileHead[num].afDataSize + sizeof(ADPFILEHEAD) )
		{
		pio_putstr("ファイルの長さが異常です。\n");
		pio_fclose(fp);
		return	0;
		}

	// データをKRAMに転送し、構造体にパラメータをセットする
	pcmblock += AdpcmDataSet(&pInfo[num], (unsigned short *)pcmbuffer,
									(unsigned short)pcmblock, PCM_NORMAL);
	pio_putstr("成功。\n");
	pio_fclose(fp);
	return	1;
	}


// スプライト関係 -------------------------------------------------------------

/*
 * スプライト登録
 */
void
SrcSet(unsigned short bank, int xsize, int ysize, int xnum, int ynum)
	{
	int	i,j,n;

	for ( i = 0 ; i < ynum ; i++ )
		{
		for ( j = 0 ; j < xnum ; j++ )
			{
			src[charnumber].bank   = bank;
			src[charnumber].x_pos  = j*xsize;
			src[charnumber].y_pos  = i*ysize;
			src[charnumber].x_size = xsize;
			src[charnumber].y_size = ysize;
			src[charnumber].x_hot  = xsize/2;
			src[charnumber].y_hot  = ysize/2;
			charnumber++;
			}
		}
	}

/*
 * スプライト表示
 */
void
SprPut(int x,int y,int pat)
	{
	ASLMakeSimpleSprite( &src[pat], x, y, &sct);

	sct.cntl |= 0x0030;		// Hidden Clearを使うときの処理
	sct.cntl &= 0xfffc;		// 同上

	ASLSetSpriteTable( 15, 0, 1, &sct );
	ASLExecuteSprite( 15, 0, 1 );
	}

/*
 * スプライト拡大縮小回転表示
 */
void
SprRotZoomPut(int x,int y,int r,int z,int pat)
	{
	ASLMakeZoomRotateSprite( &src[pat], x, y, r, z, &sct );

	sct.cntl |= 0x0030;		// Hidden Clearを使うときの処理
	sct.cntl &= 0xfffc;		// 同上

	ASLSetSpriteTable( 15, 0, 1, &sct );
	ASLExecuteSprite( 15, 0, 1);
	}


// 文字表示関係 ---------------------------------------------------------------

/*
 * 文字列表示
 */
void
StrDsp(int x,int y,unsigned char *str)
	{
	int	c;
	int	sx,sy;

	c = 0;
	sx = x;
	sy = y;
	while(1)
		{
		if ( str[c] == 0x00 ) break;
		if ( str[c] > 0x20 )
			{
			SprPut(sx,sy,str[c]);
			}
		sx += 8;
		if ( sx > 255 || str[c] == '\n' )
			{
			sx = x;
			sy += 8;
			}
		c++;
		}
	}

/*
 * 文字列表示(大フォント)
 */
void
StrDspBig(int x,int y,unsigned char *str)
	{
	int	c;
	int	sx,sy;

	c = 0;
	sx = x;
	sy = y;
	while(1)
		{
		if ( str[c] == 0x00 ) break;
		if ( str[c] > 0x20 )
			{
			SprPut(sx,sy,str[c]+HED_BIGFONT-0x20);
			}
		sx += 16;
		if ( sx > 255 || str[c] == '\n' )
			{
			sx = x;
			sy += 16;
			}
		c++;
		}
	}


/*
 * 数値表示
 */
void
NumDsp(int x,int y,unsigned long val)
	{
	static char dectbl[] = "0123456789";
	static char str[12];
	int i,a,c;

	str[10] = '\0';
	for ( i = 9 ; i >= 0 ; i--)
		{
		str[i] = dectbl[val % 10];
		val /= 10;
		}
	c = a = i = 0;
	while(1)
		{
		if ( str[c] == 0x00 ) break;
		if ( str[c] != '0' || c == 9 ) a = 1;
		if ( a == 1 )
			{
			SprPut(x+i*8,y,str[c]);
			i++;
			}
		c++;
		}
	}

/*
 * 数値表示(大フォント)
 */
void
NumDspBig(int x,int y,unsigned long val)
	{
	static char dectbl[] = "0123456789";
	static char str[12];
	int i,a,c;

	str[10] = '\0';
	for ( i = 9 ; i >= 0 ; i--)
		{
		str[i] = dectbl[val % 10];
		val /= 10;
		}
	c = a = i = 0;
	while(1)
		{
		if ( str[c] == 0x00 ) break;
		if ( str[c] != '0' || c == 9 ) a = 1;
		if ( a == 1 )
			{
			SprPut(x+i*16,y,str[c]+HED_BIGFONT-0x20);
			i++;
			}
		c++;
		}
	}

/*
 * 数値表示(大フォント)
 * 桁揃え版 k = 1 〜 10
 */
void
NumDspBig2(int x,int y,unsigned long val, int k)
	{
	static char dectbl[] = "0123456789";
	static char str[12];
	int i,a,c;

	str[10] = '\0';
	for ( i = 9 ; i >= 0 ; i--)
		{
		str[i] = dectbl[val % 10];
		val /= 10;
		}
	c = a = i = 0;
	while(1)
		{
		if ( str[c] == 0x00 ) break;
		if ( c >= 10 - k )
			{
			if ( str[c] != '0' || c == 9 ) a = 1;
			if ( str[c] == '0' && a == 0 )
				{
				i++;
				}
			else
				{
				SprPut(x+i*16,y,str[c]+HED_BIGFONT-0x20);
				i++;
				}
			}
		c++;
		}
	}


// パレット関係 ---------------------------------------------------------------

/*
 * パレット変更
 */
void
PaletteChange(int palettenumber, unsigned short yuv)
	{
	unsigned short	dat[2];

	dat[0] = yuv;
	write_pallet_datas(palettenumber, &dat[0], 1);
	}

/*
 * パレットフェードイン、フェードアウト
 */
void
PaletteFadeBlack(int mode,int start, int end)
	{
	int	i,j;

	if ( mode )
		{
		// fadein
		for ( i = 0 ; i < FADERATE + 1 ; i++ )
			{
			if ( i == FADERATE/2 ) KINGDispOn();
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataBlack(i,j);
				}
			if ( ButtonCheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	else
		{
		// fadeout
		for ( i = FADERATE ; i >= 0 ; i-- )
			{
			if ( i == FADERATE/2 ) KINGDispOff();
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataBlack(i,j);
				}
			if ( ButtonCheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	}

/*
 * パレットホワイトイン、ホワイトアウト
 */
void
PaletteFadeWhite(int mode,int start, int end)
	{
	int	i,j;

	if ( mode )
		{
		// whitein
		for ( i = 0 ; i < FADERATE + 1 ; i++ )
			{
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataWhite(i,j);
				}
			if ( ButtonCheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	else
		{
		// fadewhiteout
		for ( i = FADERATE ; i >= 0 ; i-- )
			{
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataWhite(i,j);
				}
			if ( ButtonCheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	}

/*
 * パレットデータ作成
 */
void
MakePaletteDataBlack(int i, int j)
	{
	int	a,b,c,p;

	a = (i5c4yuv_col[j] & 0xff00) * i / FADERATE;
	a &= 0xff00;
	p = i5c4yuv_col[j] & 0x00f0;
	if ( p > 0x0080 )
		{
		b = 0x0080 + (p - 0x0080) * i / FADERATE;
		}
	else
		{
		b = 0x0080 - (0x0080 - p) * i / FADERATE;
		}
	b &= 0x00f0;
	c = (0x0008 - (i5c4yuv_col[j] & 0xfff0)) * i / FADERATE;
	p = i5c4yuv_col[j] & 0x000f;
	if ( p > 0x0008 )
		{
		c = 0x0008 + (p - 0x0008) * i / FADERATE;
		}
	else
		{
		c = 0x0008 - (0x0008 - p) * i / FADERATE;
		}
	c &= 0x000f;
	workdat[j] = a | b | c;
	}

/*
 * パレットデータ作成2
 */
void
MakePaletteDataWhite(int i, int j)
	{
	int	a,b,c;
	unsigned short	p;

	p = i5c4yuv_col[j] & 0xff00;
	a = p + ((0xff00 - p) * (FADERATE-i) / FADERATE);
	a &= 0xff00;

	p = i5c4yuv_col[j] & 0x00f0;
	if ( p > 0x0080 )
		{
		b = 0x0080 + (p - 0x0080) * i / FADERATE;
		}
	else
		{
		b = 0x0080 - (0x0080 - p) * i / FADERATE;
		}
	b &= 0x00f0;
	c = (0x0008 - (i5c4yuv_col[j] & 0xfff0)) * i / FADERATE;
	p = i5c4yuv_col[j] & 0x000f;
	if ( p > 0x0008 )
		{
		c = 0x0008 + (p - 0x0008) * i / FADERATE;
		}
	else
		{
		c = 0x0008 - (0x0008 - p) * i / FADERATE;
		}
	c &= 0x000f;
	workdat[j] = a | b | c;
	}


// その他 ---------------------------------------------------------------------

/*
 * 乱数発生
 */
int
random(int num)
	{
	unsigned int a;

	randomseed = randomseed * 1103515245 + 12345;
	a = (randomseed/0x10000) % 0x8000;
	a %= num;
	return a;
	}

/*
 * テクスチャバッファへの書込み
 */
void
WriteTextureBuffer(int bank, int x, int y, int data)
	{
	FarlSetMemReg(FARL_CMT_BANK_SELECT_REG, bank);
	FarlWriteTxtXYUnpk(x, y, data);
	}

/*
 * 描画後処理
 */
void
DspWait()
	{
	// 描画終了待ち
	ASLSync();
	// ディスプレイバッファのスワップ
	FarlSwapWindow();
	// スワップ(フリップ)待ち
	ASLWaitForSwap();
	}

/*
 * ADPCM再生
 */
void
PcmPlay(int ch, int num)
	{
	if ( ch == 0 )
		{
		AdpcmStop(CHANNEL_1);
		AdpcmPlay(CHANNEL_1,&pInfo[num]);
		}
	else
		{
		AdpcmStop(CHANNEL_2);
		AdpcmPlay(CHANNEL_2,&pInfo[num]);
		}
	}

/*
 * 1ボタンチェック
 */
int
ButtonCheck()
	{
	get_pad();
	if ( pad00.KD_DAT & KP_1 )
		{
		skipflag = 1;
		return	1;
		}
	return	0;
	}

/*
 * ウェイト
 */
void
Wait(int c)
	{
	int	i,j;
	int	a,b;

	for ( i = 0 ; i < c ; i++ )
		{
		if ( ButtonCheck() ) return;
		VSyncWait();
		}
	}

/*
 * Loading Dsplay
 */
void
LoadDsp(int num,int sum)
	{
	int	percent;

	percent = num * 100 / sum;
	StrDsp(16,218,"Now Loading...");
	NumDsp(128,218,percent);
	if ( percent < 10 )
		{
		StrDsp(136,218,"%");
		}
	else if ( percent > 99 )
		{
		StrDsp(152,218,"%");
		}
	else
		{
		StrDsp(144,218,"%");
		}
	DspWait();
	}

